﻿# ---------------------------------------------------------- #
# Active Directory Domain Services (ADDS) Site Configuration #
# ---------------------------------------------------------- #
param([string]$virtualMachineService, [string]$virtualMachineName)

Write-Information "Virtual machine '$virtualMachineName' executing Active Directory site '$($script.type)' configuration ... " -NoNewLine $true
$userName = $subscription.virtualMachines.adminUserName
$password = $subscription.virtualMachines.password
$netBiosDomain = $subscription.virtualMachines.netBiosDomain
$uri = Get-AzureWinRMUri -ServiceName $virtualMachineService -Name $virtualMachineName
$credential = New-Object System.Management.Automation.PSCredential(($netBiosDomain + "\" + $userName), (ConvertTo-SecureString $password -AsPlainText -Force))
$session = New-PSSession -ComputerName $uri[0].DnsSafeHost -Credential $credential -Port (Get-VirtualMachineInstanceEndpointPort $subscription $virtualMachineName) -UseSSL
switch ($script.type)
{
	"Create"
	{
		Invoke-Command -Session $session -ScriptBlock {
		    param([string]$siteName, [string]$siteSubnet)
            Import-Module ActiveDirectory
            if ((Get-ADReplicationSite -Filter {Name -eq $siteName}) -eq $null)
            {
                New-ADReplicationSite -Name $siteName
				Get-ADReplicationSiteLink -Identity "DEFAULTIPSITELINK" | Set-ADReplicationSiteLink -SitesIncluded @{Add="$siteName"}
            }
            Get-ADReplicationSubnet -Filter {Name -eq $siteSubnet} | Remove-ADReplicationSubnet -Confirm:$false
            New-ADReplicationSubnet -Name $siteSubnet -Site $siteName
		} -ArgumentList $script.siteName, $script.siteSubnet
	}
	"Rename"
	{
		Invoke-Command -Session $session -ScriptBlock {
		    param([string]$fromSite, [string]$toSite)
            Import-Module ActiveDirectory
            Get-ADObject -SearchBase (Get-ADRootDSE).configurationNamingContext -Filter {ObjectClass -eq "site"} | ? {$_.Name -eq $fromSite} | Rename-ADObject -NewName $toSite
		} -ArgumentList $script.fromSite, $script.toSite
	}
	"Connect"
	{
		Invoke-Command -Session $session -ScriptBlock {
		    param([string]$sourceServer)
            $connectionName = $sourceServer.ToUpper()
            $domainDN = (Get-ADDomain).DistinguishedName
            $sourceServerDN = (Get-ADObject -LDAPFilter "(&(cn=$sourceServer)(objectClass=server))" -SearchBase "CN=Configuration,$domainDN").DistinguishedName
            $sourceServerNTDS = [adsi]"LDAP://$Env:COMPUTERNAME.$Env:USERDNSDOMAIN/CN=NTDS Settings,$sourceServerDN"
            $currentServerDN = (Get-ADObject -LDAPFilter "(&(cn=$Env:COMPUTERNAME)(objectClass=server))" -SearchBase "CN=Configuration,$domainDN").DistinguishedName
            $currentServerNTDS = [adsi]"LDAP://$Env:COMPUTERNAME.$Env:USERDNSDOMAIN/CN=NTDS Settings,$currentServerDN"
            $connection = $currentServerNTDS.psbase.Children.Add("CN=$connectionName", "nTDSConnection")
            $connection.psbase.Properties["fromServer"].Value = $sourceServerNTDS.distinguishedName.Value
            $connection.psbase.Properties["Options"].Value = 0
            $connection.psbase.Properties["enabledConnection"].Value = $true
            $connection.psbase.CommitChanges()
		} -ArgumentList $script.sourceServer
	}
	"Replicate"
	{
		Invoke-Command -Session $session -ScriptBlock {
		    param([string]$fromDC, [string]$toDC)
            $domainDN = (Get-ADDomain).DistinguishedName
            Repadmin /replicate $toDC $fromDC "$domainDN" | Out-Null
            Repadmin /replicate $toDC $fromDC "CN=Configuration,$domainDN" | Out-Null
            Repadmin /replicate $toDC $fromDC "CN=Schema,CN=Configuration,$domainDN" | Out-Null
            Repadmin /replicate $toDC $fromDC "DC=DomainDnsZones,$domainDN" | Out-Null
            Repadmin /replicate $toDC $fromDC "DC=ForestDnsZones,$domainDN" | Out-Null
		} -ArgumentList $script.fromDC, $script.toDC
        # Troubleshooting:
        # - dcdiag /test:dns
        # - dcdiag /test:replications
        # - repadmin /showrepl
        # - Get-ADReplicationFailure -Target <DC>
        # - Get-ADReplicationQueueOperation -Server <DC>
        # - Get-ADReplicationUpToDatenessVectorTable -Target <DC>
		# Check which site a machine belongs to:
		# - $Env:LOGONSERVER
		# - nltest /dsgetdc:<domain_name>
		# - nltest /dclist:<domain_name>
		# - Get-Item HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\DynamicSiteName
    }
	"Sync"
	{
		Invoke-Command -Session $session -ScriptBlock {
            Repadmin /kcc $Env:COMPUTERNAME | Out-Null
            Repadmin /syncall /A /e $Env:COMPUTERNAME | Out-Null
		}
    }
	default
	{
		throw "Active Directory site type '$($script.type)' is not supported."
	}
}
Remove-PSSession $session
Write-Text "done."